package com.noble.glamour.module.logic.socket.stream;

import com.noble.glamour.module.logic.socket.NetData;
import com.noble.glamour.module.logic.socket.listener.SocketConnectionListener;
import com.noble.glamour.module.logic.socket.logic.KeepAliveSocket;
import com.noble.glamour.module.logic.socket.logic.task.SocketIoHandler;
import com.noble.glamour.module.logic.socket.logic.task.SubTread;
import com.noble.glamour.module.logic.socket.logic.task.ThreadRunner;
import com.noble.glamour.module.logic.socket.utils.IMUtils;

import java.io.IOException;
import java.io.InputStream;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

/**
 * 读取数据包
 */
public class PackerReader implements ThreadRunner {
    private Executor singleDispatchExecutor = Executors.newSingleThreadExecutor();

    private volatile boolean endWithException = false;
    private boolean isShutDown = false;

    private SubTread readThread;
    private InputStream input;
    private SocketConnectionListener listener;    // socket连接状态监听

    public PackerReader(SocketConnectionListener listener) {
        this.listener = listener;
    }

    @Override
    public void run() {
        readPacket();
    }

    public void init(KeepAliveSocket client, InputStream input) {
        this.input = input;

        isShutDown = false;
        endWithException = false;

        readThread = new SubTread(client, this);
        readThread.start();
        IMUtils.log("Socket read packet thread init and start");
    }

    private void readPacket() {
        try {
            while (!done()) {
                IMUtils.log("Socket read packet thread start read");
                NetData data = NetStream.parseNetData(input);
                if (data != null) {  // 分发流中读取消息
                    dispatchPacket(data);
                } else {
                    IMUtils.log("Socket read packet dispatch packet null");
                }
                Thread.sleep(15);
            }
        } catch (IOException e) {
            if (!isShutDown) {
                endWithException = true;
                IMUtils.log("Socket read packet error:" + e.getMessage());
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        //注意消息顺序
        if (endWithException) {
            readThread.handler.sendEmptyMessage(SocketIoHandler.IO_ERROR);
        }
        readThread.handler.sendEmptyMessage(SocketIoHandler.READER_CLOSE);

        IMUtils.log("Socket read packet thread shutdown done with exception:" + endWithException);
    }

    public boolean isEndWithException() {
        return endWithException;
    }

    private boolean done() {
        return isShutDown;
    }

    public void shutdown(boolean instant) {
        if (isShutDown) {
            return;
        }
        IMUtils.log("Socket read packet thread shutdown instant:" + instant + " start");
        isShutDown = true;
        try {
            IMUtils.log("Socket read packet thread shutdown wait for done start");
            input.close();
            readThread.interrupt();
            IMUtils.log("Socket read packet thread shutdown wait for done end");

        } catch (IOException e) {
            e.printStackTrace();
        }
        IMUtils.log("Socket read packet thread shutdown instant:" + instant + " end");
    }

    /**
     * 将读到的数据包分发
     */
    private void dispatchPacket(final NetData data) {
        if (listener != null) {
            singleDispatchExecutor.execute(() -> listener.onReceivePacket(data));
        }
    }
}
